package com.henry.framework;

import com.henry.framework.bean.Data;
import com.henry.framework.bean.Handler;
import com.henry.framework.bean.Param;
import com.henry.framework.bean.View;
import com.henry.framework.helper.BeanHelper;
import com.henry.framework.helper.ConfigHelper;
import com.henry.framework.helper.ControllerHelper;
import com.henry.framework.util.CodecUtil;
import com.henry.framework.util.JsonUtil;
import com.henry.framework.util.ReflectionUtil;
import com.henry.framework.util.StreamUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by 峥桂 on 2017/5/7.
 */
@WebServlet(urlPatterns = "/*",loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //初始化相关 Helper类
        HelperLoader.init();
        //获取ServletContext 对象（用于注册Servlet）
        ServletContext servletContext = servletConfig.getServletContext();
        //注册处理jsp的servlet
        ServletRegistration jspServlet=servletContext.getServletRegistration("jsp");
        jspServlet.addMapping(ConfigHelper.getApp_jsp_path()+"*");

        ServletRegistration defaultServlet=servletContext.getServletRegistration("default");
        defaultServlet.addMapping(ConfigHelper.getApp_asset_path()+"*");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.service(req, resp);
        //获取请求方法与请求路径
        String requestMethod=req.getMethod().toLowerCase();
        String requestPath=req.getPathInfo();
        //获取Action处理器
        Handler handler= ControllerHelper.getHandler(requestMethod,requestPath);
        if(handler!=null){
            //获取Controller类及其Bean实例
            Class<?> controllerClass=handler.getControllerClass();

            Object controllerBean = BeanHelper.getBean(controllerClass);
            //创建请求参数对象
            Map<String, Object> paramMap = getReqParamMap(req);
            Param param=new Param(paramMap);
            //调用Action方法
            Method actionMethod =handler.getActionMethod();
            Object result= ReflectionUtil.invokeMethod(controllerBean,actionMethod,param);
            //处理action方法返回值
            handleActionResult(req, resp, result);
        }else{
            if(requestPath.indexOf("/")==0 && requestPath.length()==1){

            }else{
                resp.sendRedirect(req.getContextPath()+"/404.jsp");
            }
            //throw new RuntimeException("not found request url");
        }

    }

    private void handleActionResult(HttpServletRequest req, HttpServletResponse resp, Object result) throws IOException, ServletException {
        if(result instanceof View){
            View view=(View)result;
            String path=view.getPath();
            if(StringUtils.isNotBlank(path)){
                if(path.startsWith("/")){
                    resp.sendRedirect(req.getContextPath()+path);
                }else {
                    Map<String,Object> model=view.getModel();
                    for(Map.Entry<String,Object> entry:model.entrySet()){
                        req.setAttribute(entry.getKey(),entry.getValue());
                    }
                    req.getRequestDispatcher(ConfigHelper.getApp_jsp_path()+path).forward(req,resp);
                }
            }
        }else if(result instanceof Data){
            Data data=(Data) result;
            Object model = data.getModel();
            if(model!=null){
                resp.setContentType("application/json");
                resp.setCharacterEncoding("UTF-8");
                PrintWriter writer=resp.getWriter();
                String json= JsonUtil.toJson(model);
                writer.write(json);
                writer.flush();
                writer.close();
            }
        }
    }

    private Map<String, Object> getReqParamMap(HttpServletRequest req) throws IOException {
        Map<String,Object> paramMap=new HashMap<>();
        Enumeration<String> paramNames=req.getParameterNames();
        while (paramNames.hasMoreElements()){
            String paramName=paramNames.nextElement();
            String paramVlaue=req.getParameter(paramName);
            paramMap.put(paramName,paramVlaue);
        }
        //TODO
        String body= CodecUtil.decodeURL(StreamUtil.getString(req.getInputStream()));
        if(StringUtils.isNotBlank(body)){
            String[] params=StringUtils.split(body,"&");
                if(ArrayUtils.isNotEmpty(params)){
                for (String param : params) {
                    String[] array=StringUtils.split(param,"=");
                    if(ArrayUtils.isNotEmpty(array) && array.length==2){
                        String paramName=array[0];
                        String paramValue=array[1];
                        paramMap.put(paramName,paramValue);
                    }
                }
            }
        }
        return paramMap;
    }
}
